package com.ls.rabbitmqService.base;

import com.ls.rabbitmqService.utils.ConnectionFactoryUtil;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;

public class Send {

    //为队列起个name
    private static String QUEUE_NAME="test";

    public static void main(String[] args){
        Connection connection =null;
        Channel channel=null;
        try {
             connection = ConnectionFactoryUtil.getRabbitConnection();
             channel = connection.createChannel();
            //queue队列的持久化 durable 参数代表是否需要持久化，true代表是  rabbitmq服务器重起可以保证消息可以再次被消费
            channel.queueDeclare(QUEUE_NAME,true,false,false,null);
            String message="hello world!";

            //发送消息时设置消息的持久化
            AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
            //这里的deliveryMode=1代表不持久化，deliveryMode=2代表持久化。
            builder.deliveryMode(1);
            AMQP.BasicProperties properties = builder.build();

            /**
             *
             * 正常情况下，如果消息经过交换器进入队列就可以完成消息的持久化，
             * 但如果消息在没有到达broker之前出现意外，那就造成消息丢失，有没有办法可以解决这个问题？
             * RabbitMQ有两种方式来解决这个问题：
             * 1.通过AMQP提供的事务机制实现；
             * 2.使用发送者确认模式实现；
             *
             * 测试1w数据发送  时间为毫秒
             *
             * 第一种发送的时候不采取任何操作  480 540 560
             *
             * 第二种增加是事物 877 997 729
             *
             * 第三种增加confirm确认  713 720 872
             */

            long start_time= System.currentTimeMillis();
            //channel.txSelect(); //声明事务，声明事务访问的

            //开启发送方确认模式
            //channel.confirmSelect();
            for(int i=0;i<10000;i++){
                message=message+"i";
                channel.basicPublish("",QUEUE_NAME,properties,message.getBytes());
                //System.out.println(String.format("[x] Send %s",message));
            }
            //channel.txCommit();
            //异步监听确认和未确认的消息
            /*channel.addConfirmListener(new ConfirmListener() {
                @Override
                public void handleNack(long deliveryTag, boolean multiple) throws IOException {
                    System.out.println("未确认消息，标识：" + deliveryTag);
                }
                @Override
                public void handleAck(long deliveryTag, boolean multiple) throws IOException {
                    //可以看到批量发送的消息并不是通过1次进行确认的有时候是多条一块确认的，可能是很多条
                    System.out.println(String.format("已确认消息，标识：%d，多个消息：%b", deliveryTag, multiple));
                }
            });*/
            long end_time= System.currentTimeMillis();
            System.out.println("send time:"+ (end_time-start_time) );



        } catch (IOException e) {
            //采用事物确认模式
           /* try {
                channel.txRollback();
            } catch (IOException e1) {
                e1.printStackTrace();
            }*/
            e.printStackTrace();
        } finally{
            /*if(channel!=null){
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (TimeoutException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }*/
        }

    }

}
